home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / firefox-3.0.14 / chrome / browser.jar / content / browser / places / toolbar.xml < prev    next >
Encoding:
Extensible Markup Language  |  2008-05-28  |  40.5 KB  |  1,103 lines

  1. <?xml version="1.0"?>
  2.  
  3.  
  4.  
  5. <!DOCTYPE bindings [
  6. <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
  7. %browserDTD;
  8. ]>
  9.  
  10. <bindings id="placesToolbarBindings"
  11.           xmlns="http://www.mozilla.org/xbl"
  12.           xmlns:xbl="http://www.mozilla.org/xbl"
  13.           xmlns:html="http://www.w3.org/1999/xhtml"
  14.           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  15.  
  16.   <binding id="places-bar">
  17.     <resources>
  18.       <stylesheet src="chrome://browser/skin/places/places.css"/>
  19.     </resources>
  20.  
  21.     <content>
  22.       <xul:vbox>
  23.         <xul:hbox class="toolbar-drop-indicator-bar">
  24.           <xul:hbox class="toolbar-drop-indicator"/>
  25.         </xul:hbox>
  26.         <xul:hbox flex="1">
  27.           <xul:hbox class="bookmarks-toolbar-items places-toolbar-items" flex="1">
  28.             <children/>
  29.           </xul:hbox>
  30.           <xul:toolbarbutton class="bookmark-item bookmarks-toolbar-customize"
  31.                              mousethrough="never"
  32.                              label="&bookmarksToolbarItem.label;"/>
  33.         </xul:hbox>
  34.       </xul:vbox>
  35.       <xul:hbox mousethrough="always"
  36.                 flex="1"
  37.                 pack="end">
  38.         <xul:toolbarbutton type="menu"
  39.                            class="chevron"
  40.                            mousethrough="never"
  41.                            collapsed="true"
  42.                            onpopupshowing="chevronPopupShowing(event);">
  43.           <xul:menupopup anonid="chevronPopup"
  44.                          context="placesContext"
  45.           />
  46.         </xul:toolbarbutton>
  47.       </xul:hbox>
  48.     </content>
  49.  
  50.     <implementation>
  51.       <constructor><![CDATA[
  52.         this._init();
  53.       ]]></constructor>
  54.  
  55.       <destructor><![CDATA[
  56.         if (this._result) {
  57.           this._result.viewer = null;
  58.           this._result = null;
  59.         }
  60.       ]]></destructor>
  61.  
  62.       <property name="controller"
  63.                 readonly="true"
  64.                 onget="return this._controller;"/>
  65.  
  66.       <method name="_init">
  67.         <body><![CDATA[
  68.         this._controller = new PlacesController(this);
  69.         this.controllers.appendController(this._controller);
  70.  
  71.         var t = this;
  72.         window.addEventListener("resize",
  73.                                 function f(e) { t.updateChevron(e); },
  74.                                 false);
  75.  
  76.         if (this.hasAttribute("place")) {
  77.           // Do the initial build. 
  78.           this.place = this.place;
  79.         }
  80.         ]]></body>
  81.       </method>
  82.  
  83.       <field name="_dropIndicatorBar">document.getAnonymousElementByAttribute(this, "class", "toolbar-drop-indicator-bar")</field>
  84.       <field name="_chevron">document.getAnonymousElementByAttribute(this, "class", "chevron")</field>
  85.  
  86.       <field name="_openedMenuButton">null</field>
  87.  
  88.       <field name="_result">null</field>
  89.  
  90.       <!-- nsIPlacesView -->
  91.       <method name="getResult">
  92.         <body><![CDATA[
  93.           return this._result;
  94.         ]]></body>
  95.       </method>
  96.  
  97.       <!-- nsIPlacesView -->
  98.       <method name="getResultNode">
  99.         <body><![CDATA[
  100.           return this._result.root;
  101.         ]]></body>
  102.       </method>
  103.  
  104.       <method name="_rebuild">
  105.         <body><![CDATA[
  106.           // Clear out references to existing nodes, since we'll be deleting and re-adding.
  107.           if (this._DNDObserver._overFolder.node)
  108.             this._DNDObserver._clearOverFolder();
  109.           this._openedMenuButton = null;
  110.  
  111.           while (this.hasChildNodes())
  112.             this.removeChild(this.firstChild);
  113.  
  114.           var rootNode = this._result.root;
  115.           var cc = rootNode.childCount;
  116.           for (var i = 0; i < cc; ++i)
  117.             this.insertNewItem(rootNode.getChild(i), null);
  118.  
  119.           var chevronPopup = this._chevron.lastChild;
  120.           if (chevronPopup.hasAttribute("type")) {
  121.             // Otherwise we'll set it when the chevron is enabled (see updateChevron)
  122.             chevronPopup.place = this.place;
  123.           }
  124.  
  125.           while (chevronPopup.hasChildNodes())
  126.             chevronPopup.removeChild(chevronPopup.lastChild);
  127.  
  128.           // This needs to be in a timeout to make sure our boxObject has time
  129.           // to get its proper size
  130.           var t = this;
  131.           setTimeout(function() { t.updateChevron(); }, 0);
  132.         ]]></body>
  133.       </method>
  134.  
  135.       <method name="insertNewItem">
  136.         <parameter name="aChild"/>
  137.         <parameter name="aBefore"/>
  138.         <body><![CDATA[
  139.           var type = aChild.type;
  140.           var button;
  141.           if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
  142.             button = document.createElement("toolbarseparator");
  143.           else {
  144.             button = document.createElement("toolbarbutton");
  145.             button.className = "bookmark-item";
  146.             button.setAttribute("label", aChild.title);
  147.             var iconURI = aChild.icon;
  148.             var iconURISpec = "";
  149.             if (iconURI) {
  150.               iconURISpec = iconURI.spec;
  151.               button.setAttribute("image", iconURISpec);
  152.             }
  153.  
  154.             if (PlacesUtils.containerTypes.indexOf(type) != -1) {
  155.               button.setAttribute("type", "menu");
  156.               button.setAttribute("container", "true");
  157.  
  158.               if (PlacesUtils.nodeIsQuery(aChild)) {
  159.                 button.setAttribute("query", "true");
  160.                 if (PlacesUtils.nodeIsTagQuery(aChild))
  161.                   button.setAttribute("tagContainer", "true");
  162.               }
  163.               else if (PlacesUtils.nodeIsLivemarkContainer(aChild))
  164.                 button.setAttribute("livemark", "true");
  165.  
  166.               var popup = document.createElement("menupopup");
  167.               popup.setAttribute("placespopup", "true");
  168.               button.appendChild(popup);
  169.               popup._result = this._result;
  170.               popup._resultNode = asContainer(aChild);
  171.               popup.setAttribute("context", "placesContext");
  172.               this._containerNodesMap.push({ resultNode: aChild,
  173.                                              domNode: popup });
  174.             }
  175.           }
  176.  
  177.           button.node = aChild;
  178.           button.node.viewIndex = 0;
  179.           if (aBefore)
  180.             this.insertBefore(button, aBefore);
  181.           else
  182.             this.appendChild(button);
  183.         ]]></body>
  184.       </method>
  185.  
  186.       <method name="removeItem">
  187.         <parameter name="child"/>
  188.         <body><![CDATA[
  189.           if (PlacesUtils.nodeIsContainer(child.node)) {
  190.             for (var i=0; i < this._containerNodesMap.length; i++) {
  191.               if (this._containerNodesMap[i].resultNode == child.node) {
  192.                 this._containerNodesMap.splice(i, 1);
  193.                 break;
  194.               }
  195.             }
  196.           }
  197.  
  198.           // if document.popupNode pointed to this child, null it out,
  199.           // otherwise controller's command-updating may rely on the removed
  200.           // item still being "selected".
  201.           if (document.popupNode == child)
  202.             document.popupNode = null;
  203.           child.parentNode.removeChild(child);
  204.         ]]></body>
  205.       </method>
  206.  
  207.       <method name="chevronPopupShowing">
  208.         <parameter name="aEvent"/>
  209.         <body><![CDATA[
  210.           var popup = aEvent.target;
  211.           if (popup != this._chevron.firstChild)
  212.             return;
  213.  
  214.           for (var i = 0; i < popup.childNodes.length; i++)
  215.             popup.childNodes[i].hidden = !this.childNodes[i].collapsed;
  216.         ]]></body>
  217.       </method>
  218.  
  219.       <method name="getElementWidth">
  220.         <parameter name="element"/>
  221.         <body><![CDATA[
  222.           var style = document.defaultView.getComputedStyle(element, "");
  223.           var leftMargin = style.getPropertyValue("margin-left");
  224.           leftMargin = leftMargin ? Math.round(parseFloat(leftMargin)) : 0;
  225.           var rightMargin = style.getPropertyValue("margin-right");
  226.           rightMargin = rightMargin ? Math.round(parseFloat(rightMargin)) : 0;
  227.           return element.boxObject.width + leftMargin + rightMargin;
  228.         ]]></body>
  229.       </method>
  230.  
  231.       <method name="updateChevron">
  232.         <parameter name="event"/>
  233.         <body><![CDATA[
  234.           // Ignore events that aren't on the document or the window
  235.           // (html document, tooltips, etc)
  236.           // Do not ignore content window resizes, because they may
  237.           // be the result of the toolbar being shown/hidden
  238.           if (event && event.target != document && event.target != window &&
  239.               event.target != content)
  240.             return;
  241.  
  242.           if (this.childNodes.length == 0) {
  243.             this._chevron.collapsed = true;
  244.             return;
  245.           }
  246.  
  247.           var spaceLeft = this.boxObject.width;
  248.           this._chevron.collapsed = false;
  249.           var chevronWidth = this._chevron.boxObject.width;
  250.           var overflowed = false;
  251.           for (var i = 0; i < this.childNodes.length; i++) {
  252.             var child = this.childNodes[i];
  253.             child.collapsed = false;
  254.             spaceLeft -= this.getElementWidth(child);
  255.             var spaceNeeded = (i == this.childNodes.length - 1) ? 0 : chevronWidth;
  256.             if (spaceLeft < spaceNeeded) {
  257.               overflowed = true;
  258.               child.collapsed = true;
  259.             }
  260.           }
  261.           if (!(this._chevron.collapsed = !overflowed)) {
  262.             // Attach the popup binding to the chevron popup
  263.             var popup = this._chevron.firstChild;
  264.             if (!popup.hasAttribute("type")) {
  265.               popup.setAttribute("place", this.place);
  266.               popup.setAttribute("type", "places");
  267.             }
  268.           }
  269.         ]]></body>
  270.       </method>
  271.  
  272.       <!-- nsIPlacesView -->
  273.       <property name="place">
  274.         <getter><![CDATA[
  275.           return this.getAttribute("place");
  276.         ]]></getter>
  277.         <setter><![CDATA[ 
  278.           this.setAttribute("place", val);
  279.  
  280.           var history = PlacesUtils.history;
  281.           var queries = { }, options = { };
  282.           history.queryStringToQueries(val, queries, { }, options);
  283.           if (!queries.value.length) 
  284.             queries.value = [history.getNewQuery()];
  285.           try {
  286.             var result =
  287.               history.executeQueries(queries.value, queries.value.length,
  288.                                      options.value);
  289.             result.viewer = this._viewer;
  290.           }
  291.           catch(ex) {
  292.             // Invalid query, or had no results.
  293.             // This is valid, eg: user deletes their bookmarks toolbar folder. 
  294.           }
  295.           return val;
  296.         ]]></setter>
  297.       </property>
  298.  
  299.       <!-- nsIPlacesView -->
  300.       <property name="hasSelection">
  301.         <getter><![CDATA[ 
  302.           return this.selectedNode != null;
  303.         ]]></getter>
  304.       </property>
  305.  
  306.       <!-- nsIPlacesView -->
  307.       <method name="getSelectionNodes">
  308.         <body><![CDATA[
  309.           var selectedNode = this.selectedNode;
  310.           return selectedNode ? [selectedNode] : [];
  311.         ]]></body>
  312.       </method>
  313.  
  314.       <!-- nsIPlacesView -->
  315.       <method name="getRemovableSelectionRanges">
  316.         <body><![CDATA[
  317.           return [this.getSelectionNodes()];
  318.         ]]></body>
  319.       </method>
  320.  
  321.       <!-- nsIPlacesView -->
  322.       <method name="getDragableSelection">
  323.         <body><![CDATA[
  324.           return [this._draggedNode];
  325.         ]]></body>
  326.       </method>
  327.  
  328.       <!-- nsIPlacesView -->
  329.       <property name="selectedNode">
  330.         <getter><![CDATA[
  331.           if (this._contextMenuShown) {
  332.             var popupNode = document.popupNode;
  333.             if (popupNode == this)
  334.               return this.getResultNode();
  335.  
  336.             return popupNode.node || popupNode.parentNode._resultNode || null;
  337.           }
  338.           return null;
  339.         ]]></getter>
  340.       </property>
  341.  
  342.       <!-- nsIPlacesView -->
  343.       <property name="insertionPoint">
  344.         <getter><![CDATA[
  345.           // By default, the insertion point is at the top level, at the end. 
  346.           var index = PlacesUtils.bookmarks.DEFAULT_INDEX;
  347.           var folderId = PlacesUtils.getConcreteItemId(this._result.root);
  348.           var orientation = Ci.nsITreeView.DROP_BEFORE;
  349.           var isTag = false;
  350.  
  351.           var selectedNode = this.selectedNode;
  352.           if (selectedNode) {
  353.             var popupNode = document.popupNode;
  354.             if (!popupNode.node) {
  355.               // If a static menuitem is selected the insertion point
  356.               // is inside the folder, at the end.
  357.               folderId = PlacesUtils.getConcreteItemId(selectedNode);
  358.               orientation = Ci.nsITreeView.DROP_ON;
  359.             }
  360.             else {
  361.               // In all other cases the insertion point is before that node.
  362.               folderId = PlacesUtils.getConcreteItemId(selectedNode.parent);
  363.               index = PlacesUtils.getIndexOfNode(selectedNode);
  364.               isTag = PlacesUtils.nodeIsTagQuery(selectedNode.parent);
  365.             }
  366.           }
  367.           return new InsertionPoint(folderId, index, orientation, isTag);
  368.         ]]></getter>
  369.       </property>
  370.  
  371.       <!-- nsIPlacesView -->
  372.       <method name="selectAll">
  373.         <body><![CDATA[ 
  374.           // Nothing
  375.         ]]></body>
  376.       </method>
  377.  
  378.       <method name="selectItems">
  379.         <body><![CDATA[
  380.           // Nothing
  381.         ]]></body>
  382.       </method>
  383.  
  384.       <!-- nsINavHistoryResultViewer -->
  385.       <field name="_viewer"><![CDATA[({
  386.         _self: this,
  387.  
  388.         _getPopupForContainer:
  389.         function PMV__getPopupForContainer(aNode) {
  390.           if (this._self._resultNode == aNode)
  391.             return this._self;
  392.  
  393.           for (var i=0; i < this._self._containerNodesMap.length; i++) {
  394.             if (this._self._containerNodesMap[i].resultNode == aNode)
  395.               return this._self._containerNodesMap[i].domNode;
  396.           }
  397.           throw("Container view not found");
  398.         },
  399.  
  400.         get result() {
  401.           return this._self._result;
  402.         },
  403.  
  404.         set result(val) {
  405.           // some methods (e.g. getURLsFromContainer) temporarily null out the
  406.           // viewer when they do temporary changes to the view, this does _not_
  407.           // call setResult(null), but then, we're called again with the result
  408.           // object which is already set for this viewer. At that point,
  409.           // we should do nothing.
  410.           if (this._self._result != val) {
  411.             this._self._containerNodesMap = [];
  412.             this._self._result = val;
  413.             if (val) // this calls _rebuild through invalidateContainer
  414.               val.root.containerOpen = true;
  415.           }
  416.           return val;
  417.         },
  418.  
  419.         itemInserted: function TV_V_itemInserted(aParentNode, aNode, aIndex) {
  420.           // don't insert new items into the toolbar
  421.           // if the parent is not the root 
  422.           if (aParentNode == this._self.getResultNode()) {
  423.             var children = this._self.childNodes;
  424.             this._self.insertNewItem(aNode,
  425.               aIndex < children.length ? children[aIndex] : null);
  426.             this._self.updateChevron();
  427.           }
  428.           else {
  429.             var popup = this._getPopupForContainer(aParentNode);
  430.             if (!popup._built)
  431.               return;
  432.  
  433.             var before = popup.childNodes[aIndex] || null;
  434.             this._self.insertNewItemToPopup(aNode, popup, before);
  435.             if (popup._emptyMenuItem)
  436.               popup._emptyMenuItem.hidden = true;
  437.           }
  438.         },
  439.  
  440.         itemRemoved: function TV_V_itemRemoved(aParentNode, aNode, aIndex) {
  441.           if (aParentNode == this._self.getResultNode()) {
  442.             var children = this._self.childNodes;
  443.             for (var i = 0; i < children.length; i++) {
  444.               if (children[i].node == aNode) {
  445.                 this._self.removeItem(children[i]);
  446.                 this._self.updateChevron();
  447.                 return;
  448.               }
  449.             }
  450.           }
  451.           else {
  452.             var popup = this._getPopupForContainer(aParentNode);
  453.             if (!popup._built)
  454.               return;
  455.  
  456.             var children = popup.childNodes;
  457.             for (var i = 0; i < children.length; i++) {
  458.               if (children[i].node == aNode) {
  459.                 this._self.removeItem(children[i]);
  460.                 if (!popup.hasChildNodes() ||
  461.                     (popup.childNodes.length == 1 &&
  462.                      popup.firstChild == popup._emptyMenuItem)) {
  463.                   this._self._showEmptyMenuItem(popup);
  464.                 }
  465.               }
  466.             }
  467.           }
  468.         },
  469.  
  470.         itemMoved:
  471.         function TV_V_itemMoved(aItem, aOldParent, aOldIndex, aNewParent,
  472.                                 aNewIndex) {
  473.           // This cannot actually happen yet (see IDL)
  474.           if (aNewParent != aOldParent)
  475.             return;
  476.  
  477.           if (aNewParent == this._self.getResultNode()) {
  478.             var children = this._self.childNodes;
  479.             for (var i = 0; i < children.length; i++) {
  480.               var button = children[i];
  481.               if (button.node == aItem) {
  482.                 this._self.removeChild(button);
  483.                 this._self.insertBefore(button, children[aNewIndex]);
  484.                 this._self.updateChevron();
  485.                 return;
  486.               }
  487.             }
  488.           }
  489.           var popup = this._getPopupForContainer(aNewParent);
  490.           var children = popup.childNodes;
  491.           for (var i = 0; i < children.length; i++) {
  492.             var menuItem = children[i];
  493.             if (menuItem.node == aItem) {
  494.               popup.removeChild(menuItem);
  495.               popup.insertBefore(menuItem, children[aNewIndex]);
  496.               return;
  497.             }
  498.           }
  499.         },
  500.  
  501.         itemChanged: function TV_V_itemChanged(aNode) {
  502.           // this check can be removed once we fix bug #382397
  503.           var parentNode = aNode.parent;
  504.           if (!parentNode)
  505.             return;
  506.  
  507.           var element;
  508.           var onToolbar = false;
  509.           if (parentNode == this._self.getResultNode()) {
  510.             onToolbar = true;
  511.             var children = this._self.childNodes;
  512.             for (var i = 0; i < children.length; i++) {
  513.               if (children[i].node == aNode) {
  514.                 element = children[i];
  515.                 break;
  516.               }
  517.             }
  518.             // Don't replace title on toolbarbuttons
  519.             var title = aNode.title;
  520.           }
  521.           else {
  522.             var popup = this._getPopupForContainer(parentNode);
  523.             if (!popup._built)
  524.               return;
  525.  
  526.             var children = popup.childNodes;
  527.             for (var i = 0; i < children.length; i++) {
  528.               if (children[i].node == aNode) {
  529.                 element = children[i];
  530.                 break;
  531.               }
  532.             }
  533.             var title = PlacesUIUtils.getBestTitle(aNode);
  534.           }
  535.  
  536.           if (PlacesUtils.nodeIsSeparator(aNode)) {
  537.             // nothing to do when a separator changes
  538.             return;
  539.           }
  540.  
  541.           var iconURI = aNode.icon;
  542.           if (iconURI) {
  543.             var spec = iconURI.spec;
  544.             if (element.getAttribute("image") != spec)
  545.               element.setAttribute("image", spec);
  546.           }
  547.           else
  548.             element.removeAttribute("image");
  549.  
  550.           if (element.getAttribute("label") != title) {
  551.             element.setAttribute("label", title);
  552.             if (onToolbar)
  553.               this._self.updateChevron();
  554.           }
  555.  
  556.           if (!element.hasAttribute("livemark") &&
  557.               PlacesUtils.nodeIsLivemarkContainer(aNode))
  558.             element.setAttribute("livemark", "true");
  559.         },
  560.  
  561.         itemReplaced:
  562.         function TV_V_itemReplaced(aParentNode, aOldNode, aNewNode, aIndex) {
  563.           if (aParentNode == this._self.getResultNode()) {
  564.             var children = this._self.childNodes;
  565.             for (var i = 0; i < children.length; i++) {
  566.               if (children[i].node == aOldNode) {
  567.                 var next = children[i].nextSibling;
  568.                 this._self.removeItem(children[i]);
  569.                 this._self.insertNewItem(aNewNode, next);
  570.                 this._self.updateChevron();
  571.                 return;
  572.               }
  573.             }
  574.           }
  575.           else
  576.             this._forwardToChildView(aParentNode, "itemReplaced", arguments);
  577.         },
  578.  
  579.         containerOpened: function TV_V_containerOpened(aNode) {
  580.           this.invalidateContainer(aNode);
  581.         },
  582.  
  583.         containerClosed: function TV_V_containerClosed(aNode) {
  584.           this.invalidateContainer(aNode);
  585.         },
  586.  
  587.         invalidateContainer: function TV_V_invalidateContainer(aContainer) {
  588.           if (aContainer == this._self.getResultNode()) {
  589.             this._self._containerNodesMap.splice(0);
  590.             this._self._rebuild();
  591.             return;
  592.           }
  593.  
  594.           function isChildOf(node, container) {
  595.             var parent = node.parent;
  596.             while (parent) {
  597.               if (parent == container)
  598.                 return true;
  599.               parent = parent.parent;
  600.             }
  601.             return false;
  602.           }
  603.  
  604.           var popupToRebuild = null;
  605.           for (var i=0; i < this._self._containerNodesMap.length; i++) {
  606.             var node = this._self._containerNodesMap[i].resultNode;
  607.             
  608.             if (node == aContainer)
  609.               popupToRebuild = this._self._containerNodesMap[i].domNode;
  610.             if (isChildOf(node, aContainer)) {
  611.               this._self._containerNodesMap.splice(i,1);
  612.               i--;
  613.             }
  614.           }
  615.  
  616.           if (popupToRebuild) {
  617.             popupToRebuild._built = false;
  618.  
  619.             // if the menupopup is open we should live-update it
  620.             if (popupToRebuild.parentNode.open)
  621.               this._self._rebuildPopup(popupToRebuild);
  622.           }
  623.         },
  624.  
  625.         invalidateAll: function TV_V_invalidateAll() {
  626.           this._self._containerNodesMap.splice(0);
  627.           this._self._rebuild();
  628.         },
  629.  
  630.         sortingChanged: function TV_V_sortingChanged(aSortingMode) {
  631.         }
  632.       })]]></field>
  633.  
  634.       <field name="_DNDObserver"><![CDATA[({
  635.         // Inside the _DNDObserver object's functions, this points to 
  636.         // the _DNDObserver object.  _self points to the toolbar xbl object.
  637.         _self: this,
  638.  
  639.         // Menu buttons should be opened when the mouse drags over them, and closed
  640.         // when the mouse drags off.  The overFolder object manages opening and closing
  641.         // of folders when the mouse hovers.
  642.         _overFolder: {node: null, openTimer: null, hoverTime: 350, closeTimer: null},
  643.  
  644.         // timer for turning of indicator bar, to get rid of flicker
  645.         _ibTimer: null, 
  646.  
  647.         _setTimer: function TBV_DO_setTimer(time) {
  648.           var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
  649.           timer.initWithCallback(this, time, timer.TYPE_ONE_SHOT);
  650.           return timer;
  651.         },
  652.  
  653.         // Function to process all timer notifications.
  654.         notify: function TBV_DO_notify(timer) {
  655.           // Timer to turn off indicator bar.
  656.           if (timer == this._ibTimer) {
  657.             ib = this._self._dropIndicatorBar.removeAttribute('dragging');
  658.             this._ibTimer = null;
  659.           }
  660.  
  661.           // Timer to open a menubutton that's being dragged over.
  662.           if (timer == this._overFolder.openTimer) {
  663.             // Set the autoopen attribute on the folder's menupopup so that
  664.             // the menu will automatically close when the mouse drags off of it.
  665.             this._overFolder.node.lastChild.setAttribute("autoopened", "true");
  666.             this._overFolder.node.open = true;
  667.             this._overFolder.openTimer = null;
  668.           }
  669.  
  670.           // Timer to close a menubutton that's been dragged off of.
  671.           if (timer == this._overFolder.closeTimer) {
  672.             // Only close the menubutton if the drag session isn't currently over
  673.             // it or one of its children.  (The autoopened attribute will let the menu
  674.             // know to close later if the menu is still being dragged over.)
  675.             var currentNode = PlacesControllerDragHelper.currentDropTarget;
  676.             var inHierarchy = false;
  677.             while (currentNode) {
  678.               if (currentNode == this._self) {
  679.                 inHierarchy = true;
  680.                 break;
  681.               }
  682.               currentNode = currentNode.parentNode;
  683.             }
  684.             // The _clearOverFolder() function will close the menu for _overFolder.node.
  685.             // So null it out if we don't want to close it.
  686.             if (inHierarchy)
  687.               this._overFolder.node = null;
  688.             
  689.             // Clear out the folder and all associated timers.
  690.             this._clearOverFolder();
  691.           }
  692.         },
  693.  
  694.         // The mouse is no longer dragging over the stored menubutton.
  695.         // Close the menubutton, clear out drag styles, and clear all
  696.         // timers for opening/closing it.
  697.         _clearOverFolder: function TBV_DO_clearOverFolder() {
  698.           if (this._overFolder.node && this._overFolder.node.lastChild) {
  699.             if (!this._overFolder.node.lastChild.hasAttribute("dragover")) {
  700.               this._overFolder.node.lastChild.hidePopup();
  701.             }
  702.             this._overFolder.node.removeAttribute("dragover");
  703.             this._overFolder.node = null;
  704.           }
  705.           if (this._overFolder.openTimer) {
  706.             this._overFolder.openTimer.cancel();
  707.             this._overFolder.openTimer = null;
  708.           }
  709.           if (this._overFolder.closeTimer) {
  710.             this._overFolder.closeTimer.cancel();
  711.             this._overFolder.closeTimer = null;
  712.           }
  713.         },
  714.  
  715.         // This function returns information about where to drop when
  716.         // dragging over this menu--insertion point, child index to drop
  717.         // before, and folder to drop into.
  718.         _getDropPoint: function TBV_DO_getDropPoint(event) {
  719.           // Can't drop if the toolbar isn't a folder.
  720.           var result = this._self.getResult();
  721.           if (!PlacesUtils.nodeIsFolder(result.root))
  722.             return null;
  723.  
  724.           var isRTL = document.defaultView
  725.                               .getComputedStyle(this._self.parentNode, "")
  726.                               .direction == "rtl";
  727.  
  728.           var dropPoint = { ip: null, beforeIndex: null, folderNode: null };
  729.           // Loop through all the nodes to see which one this should
  730.           // get dropped in/next to
  731.           for (var i = 0; i < this._self.childNodes.length; i++) {
  732.             var xulNode = this._self.childNodes[i];
  733.             if (PlacesUtils.nodeIsFolder(xulNode.node) &&
  734.                 !PlacesUtils.nodeIsReadOnly(xulNode.node)) {
  735.               // This is a folder. If the mouse is in the left 25% of the
  736.               // node (or 25% of the right, in RTL UI), drop before the folder.
  737.               // If it's in the middle 50%, drop into the folder. If it's past
  738.               // that, drop after.
  739.               if ((isRTL && event.clientX > xulNode.boxObject.x + (xulNode.boxObject.width * 0.75)) ||
  740.                   (!isRTL && event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width * 0.25))) {
  741.                 // Drop to the left of this folder.
  742.                 dropPoint.ip =
  743.                   new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
  744.                                      i, -1);
  745.                 dropPoint.beforeIndex = i;
  746.                 return dropPoint;
  747.               }
  748.               else if ((isRTL && event.clientX > xulNode.boxObject.x + (xulNode.boxObject.width * 0.25)) ||
  749.                        (!isRTL && event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width * 0.75))) {
  750.                 // Drop inside this folder.
  751.                 dropPoint.ip =
  752.                   new InsertionPoint(PlacesUtils.getConcreteItemId(xulNode.node),
  753.                                      -1, 1);
  754.                 dropPoint.beforeIndex = i;
  755.                 dropPoint.folderNode = xulNode;
  756.                 return dropPoint;
  757.               }
  758.             }
  759.             else {
  760.               // This is a non-folder node. If the mouse is left (or right, in
  761.               // RTL UI) of the middle, drop before the folder.  Otehrwise,
  762.               // we'll drop after
  763.               if ((isRTL && event.clientX > xulNode.boxObject.x + (xulNode.boxObject.width / 2)) ||
  764.                   (!isRTL && event.clientX < xulNode.boxObject.x + (xulNode.boxObject.width / 2))) {
  765.                 // Drop before this bookmark.
  766.                 dropPoint.ip =
  767.                     new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
  768.                                        i, -1);
  769.                 dropPoint.beforeIndex = i;
  770.                 return dropPoint;
  771.               }
  772.             }
  773.           }
  774.           // Should drop after the last node.
  775.           dropPoint.ip =
  776.               new InsertionPoint(PlacesUtils.getConcreteItemId(result.root),
  777.                                  -1, 1);
  778.           dropPoint.beforeIndex = -1;
  779.           return dropPoint;
  780.         },
  781.         
  782.         onDragStart: function TBV_DO_onDragStart(event, xferData, dragAction) {
  783.           // sub menus have their own d&d handlers
  784.           if (event.target.parentNode != this._self)
  785.             return false;
  786.  
  787.           if (event.target.localName == "toolbarbutton" &&
  788.               event.target.getAttribute("type") == "menu") {
  789.             return;
  790.           }
  791.  
  792.           if (event.ctrlKey)
  793.             dragAction.action = Ci.nsIDragService.DRAGDROP_ACTION_COPY;
  794.  
  795.           // activate the view and cache the dragged node
  796.           this._self._draggedNode = event.target.node;
  797.           this._self.focus();
  798.           xferData.data = this._self._controller.getTransferData(dragAction.action);
  799.         },
  800.  
  801.         canDrop: function TBV_DO_canDrop(event, session) {
  802.           var ip = this._self.insertionPoint;
  803.           return ip && PlacesControllerDragHelper.canDrop(ip);
  804.         },
  805.  
  806.         onDragOver: function TBV_DO_onDragOver(event, flavor, session) {
  807.           PlacesControllerDragHelper.currentDropTarget = event.target;
  808.           var dropPoint = this._getDropPoint(event);
  809.  
  810.           var ib = this._self._dropIndicatorBar;
  811.           if (this._ibTimer) {
  812.             this._ibTimer.cancel();
  813.             this._ibTimer = null;
  814.           }
  815.  
  816.           if (dropPoint.folderNode ||
  817.               event.originalTarget == this._self._chevron) {
  818.             // Dropping over a menubutton or chevron button
  819.             // set styles and timer to open relative menupopup
  820.             var overNode = dropPoint.folderNode || this._self._chevron;
  821.             if (this._overFolder.node != overNode) {
  822.               this._clearOverFolder();
  823.               this._overFolder.node = overNode;
  824.               this._overFolder.openTimer = this._setTimer(this._overFolder.hoverTime);
  825.             }
  826.             if (!this._overFolder.node.hasAttribute("dragover"))
  827.               this._overFolder.node.setAttribute("dragover", "true");
  828.  
  829.             ib.removeAttribute("dragging");
  830.           }
  831.           else {
  832.             // Dragging over a normal toolbarbutton,
  833.             // show indicator bar and move it to the appropriate drop point.
  834.             if (!ib.hasAttribute("dragging"))
  835.               ib.setAttribute("dragging", "true");
  836.             var ind = ib.firstChild;
  837.             var halfInd = ind.boxObject.width / 2;
  838.             var direction = document.defaultView.getComputedStyle(this._self.parentNode, "").direction;
  839.             if (direction == "ltr") {
  840.               halfInd = Math.ceil(halfInd);
  841.               if (!this._self.childNodes.length)
  842.                 ind.style.marginLeft = 0 - this._self.boxObject.x - halfInd + 'px'
  843.               else if (dropPoint.beforeIndex == -1)
  844.                 ind.style.marginLeft = this._self.lastChild.boxObject.x + 
  845.                                        this._self.lastChild.boxObject.width - this._self.boxObject.x - halfInd + 'px';
  846.               else
  847.                 ind.style.marginLeft = this._self.childNodes[dropPoint.beforeIndex].boxObject.x -
  848.                                        this._self.boxObject.x - halfInd + 'px';
  849.             }
  850.             else {
  851.               halfInd = Math.floor(halfInd);
  852.               if (this._self.childNodes.length == 0)
  853.                 ind.style.marginRight = this._self.boxObject.width + 'px';
  854.               else if (dropPoint.beforeIndex == -1) {
  855.                 ind.style.marginRight = this._self.boxObject.width -
  856.                                         (this._self.childNodes[this._self.childNodes.length - 1].boxObject.x +
  857.                                         halfInd) +'px';
  858.               }
  859.               else {
  860.                 ind.style.marginRight = this._self.boxObject.width -
  861.                                         (this._self.childNodes[dropPoint.beforeIndex].boxObject.x +
  862.                                         this._self.childNodes[dropPoint.beforeIndex].boxObject.width -
  863.                                         this._self.boxObject.x + halfInd) + 'px';
  864.               }
  865.             }
  866.             // Clear out old folder information
  867.             this._clearOverFolder();
  868.           }
  869.         },
  870.  
  871.         onDrop: function TBV_DO_onDrop(event, dropData, session) {
  872.           var dropPoint = this._getDropPoint(event);
  873.           if (dropPoint == null)
  874.             return;
  875.           PlacesControllerDragHelper.onDrop(dropPoint.ip);
  876.         },
  877.  
  878.         onDragExit: function TBV_DO_onDragExit(event, session) {
  879.           // Set timer to turn off indicator bar (if we turn it off
  880.           // here, dragenter might be called immediately after, creating
  881.           // flicker.)
  882.           if (this._ibTimer)
  883.             this._ibTimer.cancel();
  884.           this._ibTimer = this._setTimer(10);
  885.           // Close any folder being hovered over
  886.           if (this._overFolder.node)
  887.             this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime);
  888.           PlacesControllerDragHelper.currentDropTarget = null;
  889.  
  890.           this._self._draggedNode = null;
  891.         },
  892.  
  893.         getSupportedFlavours: function TBV_DO_getSupportedFlavours() {
  894.           var flavorSet = new FlavourSet();
  895.           var types = PlacesUIUtils.GENERIC_VIEW_DROP_TYPES;
  896.           for (var i = 0; i < types.length; ++i)
  897.             flavorSet.appendFlavour(types[i]);
  898.           return flavorSet;
  899.         }
  900.       })]]></field>
  901.  
  902.       <method name="checkForMenuEvent">
  903.         <parameter name="event"/>
  904.         <parameter name="action"/>
  905.         <body><![CDATA[
  906.           // It seems that even if the menu drag/drop event
  907.           // handlers set their phase to capturing, toolbarbutton
  908.           // menu events come to the toolbar first, and don't bubble.
  909.           // So if this is a menu/menuitem, try to send the event to its
  910.           // xbl handler.
  911.           if (event.target.localName.indexOf("menu") == 0) {
  912.             var parent = event.target.parentNode;
  913.             // XULDocument has no getAttribute() function, so check for it before calling.
  914.             while (parent && parent.getAttribute) {
  915.               if (parent.getAttribute("type") == "places") {
  916.                 nsDragAndDrop[action](event, parent._DNDObserver);
  917.                 return true;
  918.               }
  919.               parent = parent.parentNode;
  920.             }
  921.           }
  922.           return false;
  923.         ]]></body>
  924.       </method>
  925.  
  926.       <property name="selType" onget="return 'single';"/>
  927.  
  928.       <method name="buildContextMenu">
  929.         <parameter name="aPopup"/>
  930.         <body><![CDATA[
  931.           this._contextMenuShown = true;
  932.           this.focus();
  933.           var show = this.controller.buildContextMenu(aPopup);
  934.           if (show) {
  935.             // disable the Delete command if the selection isn't explicit
  936.             if (document.popupNode && document.popupNode.localName == "menupopup")
  937.               document.getElementById("cmd_delete").setAttribute("disabled", "true");
  938.             return true;
  939.           }
  940.           return false;
  941.         ]]></body>
  942.       </method>
  943.  
  944.       <method name="destroyContextMenu">
  945.         <parameter name="aPopup"/>
  946.         <body><![CDATA[
  947.           this._contextMenuShown = false;
  948.           if (window.content)
  949.             window.content.focus();
  950.         ]]></body>
  951.       </method>
  952.  
  953.       <method name="_showEmptyMenuItem">
  954.         <parameter name="aPopup"/>
  955.         <body><![CDATA[
  956.           if (aPopup._emptyMenuItem) {
  957.             aPopup._emptyMenuItem.hidden = false;
  958.             return;
  959.           }
  960.  
  961.           var label = PlacesUIUtils.getString("bookmarksMenuEmptyFolder");
  962.           aPopup._emptyMenuItem = document.createElement("menuitem");
  963.           aPopup._emptyMenuItem.setAttribute("label", label);
  964.           aPopup._emptyMenuItem.setAttribute("disabled", true);
  965.           aPopup.appendChild(aPopup._emptyMenuItem);
  966.         ]]></body>
  967.       </method>
  968.  
  969.       <method name="insertNewItemToPopup">
  970.         <parameter name="aChild"/>
  971.         <parameter name="aParentPopup"/>
  972.         <parameter name="aBefore"/>
  973.         <body><![CDATA[
  974.           var element =
  975.             PlacesUIUtils.createMenuItemForNode(aChild, this._containerNodesMap);
  976.  
  977.           if (aBefore)
  978.             aParentPopup.insertBefore(element, aBefore);
  979.           else {
  980.             // Add the new element to the menu.  If there is static content at
  981.             // the end of the menu, add the element before that.  Otherwise,
  982.             // just add to the end.
  983.             if (aParentPopup._endMarker != -1) {
  984.               aParentPopup.insertBefore(element,
  985.                                         aParentPopup.childNodes[aParentPopup._endMarker++]);
  986.             }
  987.             else
  988.               aParentPopup.appendChild(element);
  989.           }
  990.         ]]></body>
  991.       </method>
  992.  
  993.       <method name="_containerPopupShowing">
  994.         <parameter name="aPopup"/>
  995.         <body><![CDATA[
  996.           if (!aPopup._built)
  997.             this._rebuildPopup(aPopup);
  998.         ]]></body>
  999.       </method>
  1000.  
  1001.       <method name="_rebuildPopup">
  1002.         <parameter name="aPopup"/>
  1003.         <body><![CDATA[
  1004.           PlacesUIUtils.cleanPlacesPopup(aPopup);
  1005.  
  1006.           var resultNode = aPopup._resultNode;
  1007.           if (!resultNode.containerOpen)
  1008.             resultNode.containerOpen = true;
  1009.  
  1010.           var cc = resultNode.childCount;
  1011.           if (cc > 0) {
  1012.             if (aPopup._emptyMenuItem)
  1013.               aPopup._emptyMenuItem.hidden = true;
  1014.  
  1015.             for (var i = 0; i < cc; ++i) {
  1016.               var child = resultNode.getChild(i);
  1017.               this.insertNewItemToPopup(child, aPopup, null);
  1018.             }
  1019.           }
  1020.           else {
  1021.             // This menu is empty.  If there is no static content, add
  1022.             // an element to show it is empty.
  1023.             if (aPopup._startMarker == -1 && aPopup._endMarker == -1)
  1024.               this._showEmptyMenuItem(aPopup);
  1025.           }
  1026.           aPopup._built = true;
  1027.         ]]></body>
  1028.       </method>
  1029.     </implementation>
  1030.  
  1031.     <handlers>
  1032.       <handler event="mouseover"><![CDATA[
  1033.         var button = event.target;
  1034.         if (button.parentNode == this && button.node &&
  1035.             PlacesUtils.nodeIsURI(button.node))
  1036.           window.XULBrowserWindow.setOverLink(event.target.node.uri, null);
  1037.       ]]></handler>
  1038.       <handler event="mouseout"><![CDATA[
  1039.         window.XULBrowserWindow.setOverLink("", null);
  1040.       ]]></handler>
  1041.       <handler event="draggesture"><![CDATA[
  1042.         if (event.target.localName == "toolbarbutton" ||
  1043.             event.target.localName == "toolbarseparator")
  1044.           nsDragAndDrop.startDrag(event, this._DNDObserver);
  1045.       ]]></handler>
  1046.       <handler event="dragover"><![CDATA[
  1047.         if (!this.checkForMenuEvent(event, "dragOver"))
  1048.           nsDragAndDrop.dragOver(event, this._DNDObserver);
  1049.       ]]></handler>
  1050.       <handler event="dragdrop"><![CDATA[
  1051.         if (!this.checkForMenuEvent(event, "drop"))
  1052.           nsDragAndDrop.drop(event, this._DNDObserver);
  1053.       ]]></handler>
  1054.       <handler event="dragexit"><![CDATA[
  1055.         if (!this.checkForMenuEvent(event, "dragExit"))
  1056.           nsDragAndDrop.dragExit(event, this._DNDObserver);
  1057.       ]]></handler>
  1058.       <handler event="popupshowing" phase="capturing"><![CDATA[
  1059.         var popup = event.originalTarget;
  1060.  
  1061.         // Avoid handling popupshowing of inner views
  1062.         if (popup._resultNode && PlacesUIUtils.getViewForNode(popup) == this)
  1063.           this._containerPopupShowing(popup);
  1064.  
  1065.         var parent = popup.parentNode;
  1066.         if (parent.localName == "toolbarbutton" &&
  1067.             !PlacesControllerDragHelper.getSession())
  1068.           this._openedMenuButton = parent;
  1069.       ]]></handler>
  1070.       <handler event="popuphidden"><![CDATA[
  1071.         var popup = event.originalTarget;
  1072.  
  1073.         // Avoid handling popupshowing of inner views
  1074.         if (popup._resultNode && PlacesUIUtils.getViewForNode(popup) == this) {
  1075.           // UI performance: folder queries are cheap, keep the resultnode open
  1076.           // so we don't rebuild its contents whenever the popup is reopened.
  1077.           if (!PlacesUtils.nodeIsFolder(popup._resultNode))
  1078.             popup._resultNode.containerOpen = false;
  1079.         }
  1080.  
  1081.         var parent = popup.parentNode;
  1082.         if (parent.localName == "toolbarbutton" &&
  1083.             !PlacesControllerDragHelper.getSession())
  1084.           this._openedMenuButton = null;
  1085.       ]]></handler>
  1086.  
  1087.       <handler event="mousemove"><![CDATA[
  1088.         if (this._openedMenuButton == null || PlacesControllerDragHelper.getSession())
  1089.           return;
  1090.  
  1091.         var target = event.originalTarget;
  1092.         if (this._openedMenuButton != target &&
  1093.             target.localName == "toolbarbutton" &&
  1094.             target.type == "menu") {
  1095.           this._openedMenuButton.open = false;
  1096.           target.open = true;
  1097.         }
  1098.       ]]></handler>
  1099.     </handlers>
  1100.   </binding>
  1101.  
  1102. </bindings>
  1103.